package br.upe.dsc.caeto.ui;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.TreeMap;

import javax.swing.ActionMap;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;

import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.Action;
import org.jdesktop.application.Task;
import br.upe.dsc.caeto.core.application.Application;
import br.upe.dsc.caeto.core.CaetoManager;
import br.upe.dsc.caeto.core.ElementNotFoundException;
import br.upe.dsc.caeto.core.InvalidElementException;
import br.upe.dsc.caeto.core.cacheunit.CacheUnit;
import br.upe.dsc.caeto.core.cacheunit.CacheUnitExplorer;
import br.upe.dsc.caeto.core.cacheunit.CacheUnitSimple;
import br.upe.dsc.caeto.core.hierarchy.Hierarchy;
import br.upe.dsc.caeto.core.project.Project;
import br.upe.dsc.caeto.simulation.Simulator;

public class CaetoMainFrame extends FrameView {
    private JSeparator statusBarSeparator;
    private ActionMap actionMap;
    private JLabel statusBarMessageLabel;
    private JProgressBar progressBar;
    private JLabel statusBarAnimationLabel;
    private JTree tree;
    private JButton delAppButton;
    private JButton downAppButton;
    private JMenu editMenu;
    private JMenu fileMenu;
    private JScrollPane jScrollPane1;
    private JToolBar.Separator jSeparator1;
    private JToolBar.Separator jSeparator2;
    private JMenuBar menuBar;
    private JButton newProjectButton;
    private JButton newAppButton;
    private JButton startSimulationButton;
    private JPanel statusBarPanel;
    private JButton stopSimulationButton;
    private JToolBar toolBar;
    private JSplitPane splitPane;
    private JButton upAppButton;
    private JButton updateAppButton;
    private JTabbedPane generalTabbedPane;
    private DefaultMutableTreeNode root;
    
    private CaetoManager caetoManager;
    private int hierarchyType;
    private LinkedList<TreeMap<String, Component>> componentList;
    private TreeMap<String, Hierarchy> hierarchyList;
    private static final int HIERARQUIA_1 = 1;
    private static final int HIERARQUIA_2 = 2;
    private static final int HIERARQUIA_3 = 3;
    private static final int HIERARQUIA_4 = 4;
    private static final int HIERARQUIA_5 = 5;
	
    private JPopupMenu popup;
    
    public CaetoMainFrame(SingleFrameApplication app) {
        super(app);
        this.caetoManager = CaetoManager.getInstance();
        this.hierarchyType = HIERARQUIA_1;
        componentList = new LinkedList<TreeMap<String, Component>>();
        hierarchyList = new TreeMap<String, Hierarchy>();
        initComponents();
    }
    
    private class PopupListener extends MouseAdapter {
        public void mousePressed(MouseEvent e) {
            //maybeShowPopup(e);
        }

        public void mouseReleased(MouseEvent e) {
            maybeShowPopup(e);
        }

        private void maybeShowPopup(MouseEvent e) {
        	
            //if (e.isPopupTrigger()) {
        	if (e.getButton() == e.BUTTON1) {
                popup.show(e.getComponent(),
                		newProjectButton.getX(), newProjectButton.getHeight());
            }
        }
    }
    
    private void initComponents() {
    	actionMap = getContext().getActionMap(this);
    	menuBar = new javax.swing.JMenuBar();
    	fileMenu = new javax.swing.JMenu();
    	editMenu = new javax.swing.JMenu();
    	splitPane = new javax.swing.JSplitPane();
    	jScrollPane1 = new javax.swing.JScrollPane();
    	statusBarPanel = new javax.swing.JPanel();
    	statusBarSeparator = new javax.swing.JSeparator();
    	statusBarMessageLabel = new javax.swing.JLabel();
    	progressBar = new javax.swing.JProgressBar();
    	statusBarAnimationLabel = new javax.swing.JLabel();
    	toolBar = new javax.swing.JToolBar();
    	newProjectButton = new javax.swing.JButton();
    	newAppButton = new javax.swing.JButton();
    	delAppButton = new javax.swing.JButton();
    	updateAppButton = new javax.swing.JButton();
    	jSeparator1 = new javax.swing.JToolBar.Separator();
    	upAppButton = new javax.swing.JButton();
    	downAppButton = new javax.swing.JButton();
    	jSeparator2 = new javax.swing.JToolBar.Separator();
    	startSimulationButton = new javax.swing.JButton();
    	stopSimulationButton = new javax.swing.JButton();
    	generalTabbedPane = new javax.swing.JTabbedPane();
    	
    	initAppTree();

    	menuBar.setName("menuBar");
    	fileMenu.setName("fileMenu");
    	
    	menuBar.add(fileMenu);
    	editMenu.setName("editMenu");
    	menuBar.add(editMenu);

    	toolBar.setFloatable(false);
    	toolBar.setRollover(true);
    	toolBar.setName("toolBar");

    	popup = new JPopupMenu();
    	JMenuItem a = new JMenuItem("New Project");
    	JMenuItem b = new JMenuItem("New Application");
    	a.setAction(actionMap.get("addProject"));
    	b.setAction(actionMap.get("addApplication"));
    	a.setText("New Project");
    	b.setText("New Application");
    	//a.setName("newProject");
    	//b.setName("newAppButton");
    	popup.add(a);
    	popup.add(b);
    	MouseListener popupListener = new PopupListener();
    	
    	newProjectButton.setFocusable(false);
        newProjectButton.addMouseListener(popupListener);  	
    	newProjectButton.setHorizontalTextPosition(
    			javax.swing.SwingConstants.CENTER);
    	newProjectButton.setName("newProjectButton");
    	newProjectButton.setVerticalTextPosition(
    			javax.swing.SwingConstants.BOTTOM);
    	toolBar.add(newProjectButton);

    	newAppButton.setFocusable(false);
    	newAppButton.setHorizontalTextPosition(
    			javax.swing.SwingConstants.CENTER);
    	newAppButton.setName("newAppButton");
    	newAppButton.setVerticalTextPosition(
    			javax.swing.SwingConstants.BOTTOM);
    	//toolBar.add(newAppButton);

    	updateAppButton.setFocusable(false);
    	updateAppButton.setHorizontalTextPosition(
    			javax.swing.SwingConstants.CENTER);
    	updateAppButton.setName("updateAppButton");
    	updateAppButton.setVerticalTextPosition(
    			javax.swing.SwingConstants.BOTTOM);
    	toolBar.add(updateAppButton);

    	delAppButton.setFocusable(false);
    	delAppButton.setHorizontalTextPosition(
    			javax.swing.SwingConstants.CENTER);
    	delAppButton.setName("delAppButton");
    	delAppButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
    	toolBar.add(delAppButton);

    	toolBar.add(jSeparator1);

    	upAppButton.setFocusable(false);
    	upAppButton.setHorizontalTextPosition(
    			javax.swing.SwingConstants.CENTER);
    	upAppButton.setName("upAppButton");
    	upAppButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
    	toolBar.add(upAppButton);

    	downAppButton.setFocusable(false);
    	downAppButton.setHorizontalTextPosition(
    			javax.swing.SwingConstants.CENTER);
    	downAppButton.setName("downAppButton");
    	downAppButton.setVerticalTextPosition(
    			javax.swing.SwingConstants.BOTTOM);
    	toolBar.add(downAppButton);
    	
    	toolBar.add(jSeparator2);

    	startSimulationButton.setFocusable(false);
    	startSimulationButton.setHorizontalTextPosition(
    			javax.swing.SwingConstants.CENTER);
    	startSimulationButton.setName("startSimulationButton");
    	startSimulationButton.setVerticalTextPosition(
    			javax.swing.SwingConstants.BOTTOM);
    	toolBar.add(startSimulationButton);

    	stopSimulationButton.setFocusable(false);
    	stopSimulationButton.setHorizontalTextPosition(
    			javax.swing.SwingConstants.CENTER);
    	stopSimulationButton.setName("stopSimulationButton");
    	stopSimulationButton.setVerticalTextPosition(
    			javax.swing.SwingConstants.BOTTOM);
    	toolBar.add(stopSimulationButton);

    	statusBarMessageLabel.setName("statusBarMessageLabel");
    	statusBarAnimationLabel.setName("statusBarProgressIcon");

    	statusBarPanel.setName("statusPanel");

    	java.awt.GridBagConstraints gridBagConstraints;

    	statusBarPanel.setLayout(new java.awt.GridBagLayout());

    	statusBarSeparator.setName("statusPanelSeparator");

    	gridBagConstraints = new java.awt.GridBagConstraints();
    	gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
    	gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    	gridBagConstraints.weightx = 1.0;
    	statusBarPanel.add(statusBarSeparator, gridBagConstraints);

    	gridBagConstraints = new java.awt.GridBagConstraints();
    	gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    	gridBagConstraints.weightx = 1.0;
    	gridBagConstraints.insets = new java.awt.Insets(4, 6, 3, 3);
    	statusBarPanel.add(statusBarMessageLabel, gridBagConstraints);

    	statusBarAnimationLabel.setHorizontalAlignment(
    			javax.swing.SwingConstants.LEFT);
    	gridBagConstraints = new java.awt.GridBagConstraints();
    	gridBagConstraints.insets = new java.awt.Insets(4, 3, 4, 6);
    	statusBarPanel.add(statusBarAnimationLabel, gridBagConstraints);

    	progressBar.setName("progressBar");
    	gridBagConstraints = new java.awt.GridBagConstraints();
    	gridBagConstraints.ipady = 2;
    	gridBagConstraints.insets = new java.awt.Insets(2, 3, 2, 3);
    	statusBarPanel.add(progressBar, gridBagConstraints);

    	jScrollPane1.setViewportView(tree);

    	splitPane.setDividerLocation(170);
    	splitPane.setName("splitPane");

    	splitPane.setLeftComponent(jScrollPane1);

    	splitPane.setRightComponent(generalTabbedPane);

    	//Add actions
    	//newProjectButton.setAction(actionMap.get("addProject"));
    	//newAppButton.setAction(actionMap.get("addApplication"));
    	
    	updateAppButton.setAction(actionMap.get("saveApplication"));
    	delAppButton.setAction(actionMap.get("remove"));
    	startSimulationButton.setAction(actionMap.get("startSimulation"));

    	setComponent(splitPane);
    	setStatusBar(statusBarPanel);
    	setToolBar(toolBar);
    	setMenuBar(menuBar);

    	getFrame().pack();
    }
    
    private javax.swing.JPanel newConfigAppPanel(String appName,
    		String projectName) {
    	TreeMap<String, Component> map = new TreeMap<String, Component>();

    	JPanel configAppPanel = new javax.swing.JPanel();
        JTabbedPane appTabbedPane = new javax.swing.JTabbedPane();
        JPanel configSimulationPanel = new javax.swing.JPanel();
        JLabel benchmarkLabel = new javax.swing.JLabel();
        JTextField benchmarkTextField = new javax.swing.JTextField();
        JButton benchmarkButton = new javax.swing.JButton();
        JLabel parametersLabel = new javax.swing.JLabel();
        JTextField parametersTextField = new javax.swing.JTextField();
        JLabel inputFileLabel = new javax.swing.JLabel();
        JTextField inputFileTextField  = new javax.swing.JTextField();
        JButton inputFileButton = new javax.swing.JButton();
        JLabel outputFileLabel = new javax.swing.JLabel();
        JTextField outputFileTextField = new javax.swing.JTextField();
        JButton outputFileButton = new javax.swing.JButton();
        JPanel chooseHierarchyPanel = new javax.swing.JPanel();
        JScrollPane configHierarchyScrollPane =	new javax.swing.JScrollPane();
        JTable configHierarchyTable = new javax.swing.JTable();
        JButton hierarchy1Button = new javax.swing.JButton();
        JButton hierarchy2Button = new javax.swing.JButton();
        JButton hierarchy3Button = new javax.swing.JButton();
        JButton hierarchy4Button = new javax.swing.JButton();
        JButton hierarchy5Button = new javax.swing.JButton();
        JLabel hierarchyImageLabel = new javax.swing.JLabel();
        JSplitPane hierarchySplitPane = new javax.swing.JSplitPane();
        JPanel jPanel1 = new javax.swing.JPanel();
        JLabel simulationTypeLabel = new javax.swing.JLabel();
        JComboBox typeSimulationComboBox = new javax.swing.JComboBox();
        JSeparator jSeparator3 = new javax.swing.JSeparator();
    	JTextField projectTextField = new JTextField();

    	projectTextField.setVisible(false);
        
        map.put("projectTextField", projectTextField);
        map.put("benchmarkTextField", benchmarkTextField);
        map.put("parametersTextField", parametersTextField);
        map.put("inputFileTextField", inputFileTextField);
        map.put("outputFileTextField", outputFileTextField);
        map.put("benchmarkButton", benchmarkButton);
        map.put("inputFileButton", inputFileButton);
        map.put("outputFileButton", outputFileButton);
        map.put("typeSimulationComboBox", typeSimulationComboBox);
        map.put("configHierarchyTable", configHierarchyTable);
        map.put("hierarchyImageLabel", hierarchyImageLabel);
        map.put("hierarchy1Button", hierarchy1Button);
        map.put("hierarchy2Button", hierarchy2Button);
        map.put("hierarchy3Button", hierarchy3Button);
        map.put("hierarchy4Button", hierarchy4Button);
        map.put("hierarchy5Button", hierarchy5Button);
           
        configAppPanel.setName("configAppPanel");
        appTabbedPane.setName("appTabbedPane");
        configSimulationPanel.setName("configSimulationPane");
        benchmarkLabel.setName("benchmarkLabel");
        benchmarkTextField.setName("benchmarkTextField");
        benchmarkButton.setName("benchmarkButton");
        parametersLabel.setName("parametersLabel");
        parametersTextField.setName("parametersTextField");
        inputFileLabel.setName("inputFileLabel");
        inputFileTextField.setName("inputFileTextField");
        inputFileButton.setName("inputFileButton");
        outputFileLabel.setName("outputFileLabel");
        outputFileTextField.setName("outputFileTextField");
        outputFileButton.setName("outputFileButton");
        simulationTypeLabel.setName("simulationTypeLabel");

        projectTextField.setText(projectName);
        
        typeSimulationComboBox.setModel(new javax.swing.DefaultComboBoxModel(
        		new String[] { "Simple", "Full" }));
        typeSimulationComboBox.setName("typeHierarchyComboBox");

        javax.swing.GroupLayout configSimulationPanelLayout = new javax.swing
        							.GroupLayout(configSimulationPanel);
        configSimulationPanel.setLayout(configSimulationPanelLayout);
        configSimulationPanelLayout.setHorizontalGroup(
            configSimulationPanelLayout.createParallelGroup(
            		javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(configSimulationPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(configSimulationPanelLayout.createParallelGroup(
                	javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(benchmarkLabel, javax.swing.GroupLayout
                    		.PREFERRED_SIZE, 77, javax.swing.GroupLayout
                    		.PREFERRED_SIZE)
                    .addComponent(parametersLabel)
                    .addComponent(inputFileLabel)
                    .addComponent(outputFileLabel)
                    .addComponent(simulationTypeLabel))
                .addGap(4, 4, 4)
                .addGroup(configSimulationPanelLayout.createParallelGroup(
                	javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(configSimulationPanelLayout
                    		.createSequentialGroup()
                        .addGroup(configSimulationPanelLayout
                        		.createParallelGroup(javax.swing.GroupLayout
                        				.Alignment.LEADING)
                            .addComponent(outputFileTextField,
                            		javax.swing.GroupLayout.DEFAULT_SIZE, 346,
                            		Short.MAX_VALUE)
                            .addComponent(inputFileTextField, 
                            		javax.swing.GroupLayout.DEFAULT_SIZE, 346,
                            		Short.MAX_VALUE)
                            .addComponent(parametersTextField,
                            		javax.swing.GroupLayout.DEFAULT_SIZE, 346,
                            		Short.MAX_VALUE)
                            .addComponent(benchmarkTextField,
                            		javax.swing.GroupLayout.DEFAULT_SIZE, 346,
                            		Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle
                        		.ComponentPlacement.RELATED)
                        .addGroup(configSimulationPanelLayout
                        		.createParallelGroup(javax.swing.GroupLayout
                        				.Alignment.LEADING, false)
                            .addComponent(outputFileButton,
                            		javax.swing.GroupLayout.DEFAULT_SIZE,
                            		javax.swing.GroupLayout.DEFAULT_SIZE,
                            		Short.MAX_VALUE)
                            .addComponent(inputFileButton,
                            		javax.swing.GroupLayout.DEFAULT_SIZE,
                            		javax.swing.GroupLayout.DEFAULT_SIZE,
                            		Short.MAX_VALUE)
                            .addComponent(benchmarkButton,
                            		javax.swing.GroupLayout.DEFAULT_SIZE, 107,
                            		Short.MAX_VALUE)))
                    .addComponent(typeSimulationComboBox,
                    		javax.swing.GroupLayout.PREFERRED_SIZE, 238,
                    		javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );
        configSimulationPanelLayout.setVerticalGroup(
            configSimulationPanelLayout.createParallelGroup(javax.swing
            		.GroupLayout.Alignment.LEADING)
            .addGroup(configSimulationPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(configSimulationPanelLayout.createParallelGroup(
                		javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(benchmarkLabel)
                    .addComponent(benchmarkTextField,
                    		javax.swing.GroupLayout.PREFERRED_SIZE,
                    		javax.swing.GroupLayout.DEFAULT_SIZE,
                    		javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(benchmarkButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
                		.RELATED)
                .addGroup(configSimulationPanelLayout.createParallelGroup(
                		javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(parametersLabel)
                    .addComponent(parametersTextField,
                    		javax.swing.GroupLayout.PREFERRED_SIZE,
                    		javax.swing.GroupLayout.DEFAULT_SIZE,
                    		javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
                		.RELATED)
                .addGroup(configSimulationPanelLayout.createParallelGroup(
                		javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(inputFileLabel)
                    .addComponent(inputFileTextField,
                    		javax.swing.GroupLayout.PREFERRED_SIZE,
                    		javax.swing.GroupLayout.DEFAULT_SIZE,
                    		javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(inputFileButton))
                .addPreferredGap(javax.swing.LayoutStyle
                		.ComponentPlacement.RELATED)
                .addGroup(configSimulationPanelLayout.createParallelGroup(
                		javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(outputFileLabel)
                    .addComponent(outputFileButton)
                    .addComponent(outputFileTextField,
                    		javax.swing.GroupLayout.PREFERRED_SIZE,
                    		javax.swing.GroupLayout.DEFAULT_SIZE,
                    		javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement
                		.RELATED)
                .addGroup(configSimulationPanelLayout.createParallelGroup(
                		javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(simulationTypeLabel)
                    .addComponent(typeSimulationComboBox,
                    		javax.swing.GroupLayout.PREFERRED_SIZE,
                    		javax.swing.GroupLayout.DEFAULT_SIZE,
                    		javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(21, Short.MAX_VALUE))
        );

        appTabbedPane.addTab("Simulation", configSimulationPanel);

        configHierarchyScrollPane.setViewportView(configHierarchyTable);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing
        										.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout
            		.Alignment.LEADING)
            .addComponent(configHierarchyScrollPane,
            		javax.swing.GroupLayout.DEFAULT_SIZE, 564,
            		Short.MAX_VALUE));
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout
            		.Alignment.LEADING)
            .addComponent(configHierarchyScrollPane,
            		javax.swing.GroupLayout.DEFAULT_SIZE, 209,
            		Short.MAX_VALUE));

        appTabbedPane.addTab("Hierarchy", jPanel1);

        hierarchySplitPane.setDividerLocation(350);
        hierarchySplitPane.setName("hierarchySplitPane");

        hierarchyImageLabel.setName("hierarchyImageLabel");
        hierarchyImageLabel.setHorizontalAlignment(
        		javax.swing.SwingConstants.CENTER);
        hierarchyImageLabel.setVerticalAlignment(
        		javax.swing.SwingConstants.CENTER);
        hierarchySplitPane.setLeftComponent(hierarchyImageLabel);

        chooseHierarchyPanel.setName("chooseHierarchyPanel");
        
        hierarchy1Button.setName("hierarchy1Button");
        hierarchy2Button.setName("hierarchy2Button");
        hierarchy3Button.setName("hierarchy3Button");
        hierarchy4Button.setName("hierarchy4Button");
        hierarchy5Button.setName("hierarchy5Button");

        JButton hierarchys[] = {hierarchy1Button, hierarchy2Button,
        		hierarchy3Button, hierarchy4Button};

        hierarchy1Button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				changeHierarchyType(HIERARQUIA_1);
			}
        });
        
        hierarchy2Button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				changeHierarchyType(HIERARQUIA_2);
			}
        });
        
        hierarchy3Button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				changeHierarchyType(HIERARQUIA_3);
			}
        });
        
        hierarchy4Button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				changeHierarchyType(HIERARQUIA_4);
			}
        });
        
        javax.swing.GroupLayout chooseHierarchyPanelLayout = new javax.swing
        									.GroupLayout(chooseHierarchyPanel);
        chooseHierarchyPanel.setLayout(chooseHierarchyPanelLayout);
        chooseHierarchyPanelLayout.setHorizontalGroup(
            chooseHierarchyPanelLayout.createParallelGroup(
            		javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(chooseHierarchyPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(chooseHierarchyPanelLayout.createParallelGroup(
                		javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(hierarchy2Button,
                    		javax.swing.GroupLayout.DEFAULT_SIZE, 184,
                    		Short.MAX_VALUE)
                    .addComponent(hierarchy1Button,
                    		javax.swing.GroupLayout.DEFAULT_SIZE, 184,
                    		Short.MAX_VALUE)
                    .addComponent(hierarchy3Button,
                    		javax.swing.GroupLayout.DEFAULT_SIZE, 184,
                    		Short.MAX_VALUE)
                    .addComponent(hierarchy4Button,
                    		javax.swing.GroupLayout.DEFAULT_SIZE, 184,
                    		Short.MAX_VALUE)
                    .addComponent(hierarchy5Button,
                    		javax.swing.GroupLayout.DEFAULT_SIZE, 184,
                    		Short.MAX_VALUE))
                .addContainerGap())
        );
        chooseHierarchyPanelLayout.setVerticalGroup(
            chooseHierarchyPanelLayout.createParallelGroup(
            		javax.swing.GroupLayout.Alignment.CENTER)
            .addGroup(chooseHierarchyPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(hierarchy1Button)
                .addGap(18, 18, 18)
                .addComponent(hierarchy2Button)
                .addGap(18, 18, 18)
                .addComponent(hierarchy3Button)
                .addGap(18, 18, 18)
                .addComponent(hierarchy4Button)
                .addGap(18, 18, 18)
                .addComponent(hierarchy5Button)
                .addContainerGap(37, Short.MAX_VALUE))
        );

        hierarchySplitPane.setRightComponent(chooseHierarchyPanel);

        javax.swing.GroupLayout configAppPanelLayout = new javax.swing
        										.GroupLayout(configAppPanel);
        configAppPanel.setLayout(configAppPanelLayout);
        
        configAppPanelLayout.setHorizontalGroup(
            configAppPanelLayout.createParallelGroup(
            		javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(configAppPanelLayout.createSequentialGroup()
                .addGroup(configAppPanelLayout.createParallelGroup(
                		javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(appTabbedPane,
                    		javax.swing.GroupLayout.DEFAULT_SIZE, 569,
                    		Short.MAX_VALUE)
                    .addGroup(configAppPanelLayout.createSequentialGroup()
                        .addGap(12, 12, 12)
                        .addComponent(jSeparator3,
                        		javax.swing.GroupLayout.DEFAULT_SIZE, 557,
                        		Short.MAX_VALUE))
                    .addComponent(hierarchySplitPane,
                    		javax.swing.GroupLayout.DEFAULT_SIZE, 569,
                    		Short.MAX_VALUE))
                .addContainerGap())
        );
        configAppPanelLayout.setVerticalGroup(
            configAppPanelLayout.createParallelGroup(
            		javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
            		configAppPanelLayout.createSequentialGroup()
                .addComponent(hierarchySplitPane,
                		javax.swing.GroupLayout.DEFAULT_SIZE, 237,
                		Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle
                		.ComponentPlacement.RELATED)
                .addComponent(jSeparator3,
                		javax.swing.GroupLayout.PREFERRED_SIZE, 10,
                		javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle
                		.ComponentPlacement.RELATED)
                .addComponent(appTabbedPane,
                		javax.swing.GroupLayout.PREFERRED_SIZE, 235,
                		javax.swing.GroupLayout.PREFERRED_SIZE))
        );
    	      
        benchmarkButton.setAction(actionMap.get("openFileChooser"));
        inputFileButton.setAction(actionMap.get("openFileChooser"));
        outputFileButton.setAction(actionMap.get("openFileChooser"));
        
        getContext().getResourceManager().getResourceMap()
        			.injectComponents(configAppPanel);
        
        componentList.add(map);
       
        initConfigHierarchyTable(configHierarchyTable,
				 appName);
        loadHierarchy(HIERARQUIA_1, hierarchyImageLabel, configHierarchyTable);
        
        return configAppPanel;
    }
        
    private void addTab(String tabName, String projectName) {
    	generalTabbedPane.addTab(tabName,
    							 newConfigAppPanel(tabName, projectName));
        new CloseTabButton(generalTabbedPane,
        				   generalTabbedPane.getTabCount()-1);
    }
    
    @Action public void addProject() {
    	NewProjectDialog dialog = new NewProjectDialog(getFrame());
    	dialog.setVisible(true);
    	
    	String name = dialog.getValues()[0];
    	String path = dialog.getValues()[1];
    	
    	if (name == null && path == null) return;

    	try {
   			caetoManager.add(new Project(name, path));
		} catch (InvalidElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
    	//Add the project in the JTree
    	DefaultMutableTreeNode child = new DefaultMutableTreeNode(name);
    	
    	((javax.swing.tree.DefaultTreeModel) tree.getModel())
    		.insertNodeInto(child, root, root.getChildCount());
    	tree.scrollPathToVisible(new javax.swing.tree.TreePath(
    								child.getPath()));
    }
    
	@Action public void addApplication() {
		NewApplicationDialog dialog = new NewApplicationDialog(getFrame(),
										tree);
		dialog.setVisible(true);
		
		String name = dialog.getValues()[0];
		String projectName = dialog.getValues()[1];
		
		if (name == null) return;
		
		//Add the application in the JTree
		DefaultMutableTreeNode child = new DefaultMutableTreeNode(name);
		DefaultMutableTreeNode parent = getProjectNode(projectName);
		((javax.swing.tree.DefaultTreeModel) tree.getModel()).insertNodeInto(
				child, parent, parent.getChildCount());
		tree.scrollPathToVisible(new javax.swing.tree.TreePath(
									child.getPath()));

		//Create the default Application object
		CacheUnit cache1 = new CacheUnitSimple("il1", 1, 16, 1024);
		CacheUnit cache2 = new CacheUnitSimple("dl1", 1, 16, 1024);
		Hierarchy hierarchy = new Hierarchy(Hierarchy.HIERARCHY_1, "", "");
		try {
			hierarchy.addCacheUnit(cache1);
			hierarchy.addCacheUnit(cache2);
		}
		catch (InvalidElementException e) {
			e.printStackTrace();
		}
		Application application = new Application(name, projectName, "", "", "", "",
									hierarchy);

		try {
			Project project = caetoManager.search(projectName);
			project.getApplications().add(application);
			caetoManager.update(project);
		} catch (ElementNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        hierarchyList.put(name, (Hierarchy) hierarchy.clone());
		addTab(name, projectName);
	}
	
    @Action public void saveApplication() {
		int tabIndex = generalTabbedPane.getSelectedIndex();
		String projectName = ((JTextField) componentList.get(tabIndex)
				  .get("projectTextField")).getText();
		Application application = buildApplication(projectName, generalTabbedPane
							.getTitleAt(tabIndex),tabIndex);
		try {
			Project project = caetoManager.search(projectName);
			project.getApplications().update(application);
			caetoManager.update(project);
		} catch (ElementNotFoundException e) {
			e.printStackTrace();
		} catch (InvalidElementException e) {
			e.printStackTrace();
		}
	}
	
	@Action public void remove() {
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
											.getLastSelectedPathComponent();
		String name, projectName;
		if (tree.getModel().getRoot().equals(node.getParent().getParent())) {
			name = (String) node.getUserObject();
			projectName = (String) ((DefaultMutableTreeNode) node.getParent())
									.getUserObject();
			try {
				Project project = caetoManager.search(projectName);
				project.getApplications().remove(project
										 .getApplications().search(name));
				caetoManager.update(project);
				
				/*xxx It does not remove the node*/
				((DefaultMutableTreeNode) node.getParent())
					.remove(node);
			} catch (ElementNotFoundException e) {
				e.printStackTrace();
			} catch (InvalidElementException e) {
				e.printStackTrace();
			}
		}
	}
	
	@Action	public void openFileChooser() {
		javax.swing.JOptionPane.showMessageDialog(null, "Open");
	}

	@Action public Task startSimulation() {
		Task simulator = new Simulator(getContext().getApplication().getInstance(),
				"Project1");
		return simulator;
	}
	
	private void changeHierarchyType(int hierarchyType) {
		int tabIndex = generalTabbedPane.getSelectedIndex();
		TreeMap<String, Component> map = componentList.get(tabIndex);
		
		JLabel label = (JLabel) map.get("hierarchyImageLabel");
		JTable table = (JTable) map.get("configHierarchyTable");
		
		loadHierarchy(hierarchyType, label, table);
	}
	
	private DefaultMutableTreeNode getProjectNode(String name) {
		DefaultMutableTreeNode project;
		Enumeration<TreeNode> children = root.children();
		
    	while (children.hasMoreElements()) {
    		project = (DefaultMutableTreeNode) children.nextElement();
    		if (project.getUserObject().equals(name)) {
    			return project;
    		}
    	}
		return null;
	}
	
	private void initConfigHierarchyTable(JTable configHierarchyTable,
										  String appName){
	    String[] columnNames = {"Propriedades", "Valor"};
	    DefaultTableModel emptyModel = new DefaultTableModel(columnNames, 5);
	    configHierarchyTable.setModel(emptyModel);
	    
	    //configHierarchyTable.setInheritsPopupMenu(true);
	    configHierarchyTable.setName("configHierarchyTable");
	    configHierarchyTable.setRowHeight(20);
		configHierarchyTable.setSelectionMode(
				ListSelectionModel.SINGLE_SELECTION);
		TableColumn propertyColumn = configHierarchyTable.getColumnModel()
									 .getColumn(0);
		propertyColumn.setPreferredWidth(400);
		
		//Adiciona um botao a cada celula da colula 'Valor'
		TableColumn valueColumn = configHierarchyTable.getColumnModel()
								  .getColumn(1);
		valueColumn.setCellEditor(new ButtonEditor(getFrame(),
												   configHierarchyTable,
												   hierarchyList.get(appName)));
	}
	
	private void initAppTree() {
		root = new DefaultMutableTreeNode("Root");
		Iterable<Project> projects = caetoManager.getProjects();
		
		for (Project project : projects) {
			DefaultMutableTreeNode projectNode = new DefaultMutableTreeNode(
												 project.getName());
			Iterable<Application> applications = project.getApplications();
			for (Application application : applications) {
				projectNode.add(new DefaultMutableTreeNode(application
						            .getName()));
				hierarchyList.put(application.getName(),
		        				  (Hierarchy) application
		        				  	.getHierarquia().clone());
			}
			root.add(projectNode);
		}
		
		tree = new javax.swing.JTree(new javax.swing.tree
				.DefaultTreeModel(root));
		tree.setRootVisible(false);
		tree.addTreeSelectionListener(new AppTreeSelectionlListener());
		tree.setName("tree");
		tree.getSelectionModel().setSelectionMode(
				javax.swing.tree.TreeSelectionModel.SINGLE_TREE_SELECTION);    
	}
	
	private void loadHierarchy(int hierarchy, JLabel hierarchyImageLabel,
							   javax.swing.JTable table) {
		switch (hierarchy) {
			case HIERARQUIA_1:
                hierarchyImageLabel.setIcon(getResourceMap()
                		.getIcon("imageHierarchy1"));
				hierarchyType = HIERARQUIA_1;
				updateTable(HIERARQUIA_1, table);
				break;
			case HIERARQUIA_2:
				hierarchyImageLabel.setIcon(getResourceMap()
						.getIcon("imageHierarchy2"));
				hierarchyType = HIERARQUIA_2;
				updateTable(HIERARQUIA_2, table);
				break;
			case HIERARQUIA_3:
				hierarchyImageLabel.setIcon(getResourceMap()
						.getIcon("imageHierarchy3"));
				hierarchyType = HIERARQUIA_3;
				updateTable(HIERARQUIA_3, table);
				break;
			case HIERARQUIA_4:
				hierarchyImageLabel.setIcon(getResourceMap()
						.getIcon("imageHierarchy4"));
				hierarchyType = HIERARQUIA_4;
				updateTable(HIERARQUIA_4, table);
				break;
		}
	}
	
	private void updateTable(int hierarquia, JTable configHierarchyTable) {
		if (hierarquia == HIERARQUIA_1) {
			configHierarchyTable.getModel()
				.setValueAt("Data Cache Level 1", 0, 0);
			configHierarchyTable.getModel()
				.setValueAt("Instruction Cache Level 1", 1, 0);
			configHierarchyTable.getModel()
				.setValueAt("Data Cache Level 2", 2, 0);
			configHierarchyTable.getModel()
				.setValueAt("Instruction Cache Level 2", 3, 0);
			configHierarchyTable.getModel()
				.setValueAt("Cache Technology", 4, 0);
						
			configHierarchyTable.getModel().setValueAt("...", 0, 1);
			configHierarchyTable.getModel().setValueAt("...", 1, 1);
			configHierarchyTable.getModel().setValueAt("...", 2, 1);
			configHierarchyTable.getModel().setValueAt("...", 3, 1);
			configHierarchyTable.getModel().setValueAt("...", 4, 1);
			
		}
		else if (hierarquia == HIERARQUIA_2) {
			configHierarchyTable.getModel()
				.setValueAt("Data Cache Level 1", 0, 0);
			configHierarchyTable.getModel()
				.setValueAt("Instruction Cache Level 1", 1, 0);
			configHierarchyTable.getModel()
				.setValueAt("Cache Level 2", 2, 0);
			configHierarchyTable.getModel()
				.setValueAt("Cache Technology", 3, 0);
			configHierarchyTable.getModel()
				.setValueAt("", 4, 0);
			
			configHierarchyTable.getModel().setValueAt("", 4, 1);
			
		}
		else if (hierarquia == HIERARQUIA_3) {
			configHierarchyTable.getModel().setValueAt("Cache Level 1", 0, 0);
			configHierarchyTable.getModel().setValueAt("Cache Level 2", 1, 0);
			configHierarchyTable.getModel()
				.setValueAt("Cache Technology", 2, 0);
			configHierarchyTable.getModel().setValueAt("", 3, 0);
			configHierarchyTable.getModel().setValueAt("", 4, 0);
			
			configHierarchyTable.getModel().setValueAt("", 3, 1);
			configHierarchyTable.getModel().setValueAt("", 4, 1);
			
		}
		else if (hierarquia == HIERARQUIA_4) {
			configHierarchyTable.getModel()
				.setValueAt("Data Cache Level 1", 0, 0);
			configHierarchyTable.getModel()
				.setValueAt("Instruction Cache Level 1", 1, 0);
			configHierarchyTable.getModel()
				.setValueAt("Cache Technology", 2, 0);
			configHierarchyTable.getModel().setValueAt("", 3, 0);
			configHierarchyTable.getModel().setValueAt("", 4, 0);
						
			configHierarchyTable.getModel().setValueAt("", 3, 1);
			configHierarchyTable.getModel().setValueAt("", 4, 1);
		}
	}
	
	private void loadUpdateMode(Application application, int tabIndex) {
		TreeMap<String, Component> map = componentList.get(tabIndex);
		JTextField bechmarkTextField = (JTextField)
			map.get("benchmarkTextField");
		JTextField parametrosTextField = (JTextField)
			map.get("parametersTextField");
		JTextField entradaTextField = (JTextField)
			map.get("inputFileTextField");
		JTextField saidaTextField = (JTextField) map.get("outputFileTextField");
		JComboBox typeSimulationComboBox = (JComboBox) map
												.get("typeSimulationComboBox");		
		JLabel label = (JLabel) map.get("hierarchyImageLabel");
		JTable table = (JTable) map.get("configHierarchyTable");
		
		bechmarkTextField.setText(application.getBenchMark());
		parametrosTextField.setText(application.getParametros());
		entradaTextField.setText(application.getArquivoEntrada());
		saidaTextField.setText(application.getArquivoSaida());

		/*if (application.getHierarquia().getCacheUnits().iterator().next()
				instanceof CacheUnitSimple) {
			((JComboBox) map.get("typeSimulationComboBox")).setSelectedIndex(0);
		}
		else {
			((JComboBox) map.get("typeSimulationComboBox")).setSelectedIndex(1);
		}*/

		if (application.getHierarquia().getName().equals(Hierarchy.HIERARCHY_1)) {
			loadHierarchy(HIERARQUIA_1, label, table);
		}
		else if (application.getHierarquia().getName().equals(Hierarchy.HIERARCHY_2)) {
			loadHierarchy(HIERARQUIA_2, label, table);
		}
		else if (application.getHierarquia().getName().equals(Hierarchy.HIERARCHY_3)) {
			loadHierarchy(HIERARQUIA_3, label, table);
		}
		else if (application.getHierarquia().getName().equals(Hierarchy.HIERARCHY_4)) {
			loadHierarchy(HIERARQUIA_4, label, table);
		}
	}
	
	/*Build a new application object*/
	private Application buildApplication(String projectName, String name, int tabIndex) {
		Application application = null;
		Hierarchy hierarchy = hierarchyList.get(name);
		Iterable<CacheUnit> i = hierarchy.getCacheUnits();
		
		TreeMap<String, Component> map = componentList.get(tabIndex);
		JTextField bechmarkTextField = (JTextField)
			map.get("benchmarkTextField");
		JTextField parametrosTextField = (JTextField)
			map.get("parametersTextField");
		JTextField entradaTextField = (JTextField)
			map.get("inputFileTextField");
		JTextField saidaTextField = (JTextField) map.get("outputFileTextField");
		JComboBox typeSimulationComboBox = (JComboBox) map
												.get("typeSimulationComboBox");
		if (this.hierarchyType == HIERARQUIA_1) {
			application = new Application(name, projectName,
											bechmarkTextField.getText(),
				   	                        parametrosTextField.getText(), 
		                          			entradaTextField.getText(),
		                           			saidaTextField.getText(),
		                           			hierarchy);
			application.setTipoSimulacao((String) typeSimulationComboBox
												  .getSelectedItem());
		}
		else if (this.hierarchyType == HIERARQUIA_2) {
			application = new Application(name, projectName,
											bechmarkTextField.getText(),
                     					    parametrosTextField.getText(),
	                                        entradaTextField.getText(),
	                                        saidaTextField.getText(),
	                                        hierarchy);
			application.setTipoSimulacao((String) typeSimulationComboBox
												  .getSelectedItem());
		}
		else if (this.hierarchyType == HIERARQUIA_3) {	
			application = new Application(name, projectName,
											bechmarkTextField.getText(),
	        				              	parametrosTextField.getText(), 
											entradaTextField.getText(),
											saidaTextField.getText(),
											hierarchy);
			application.setTipoSimulacao((String) typeSimulationComboBox
												  .getSelectedItem());					
		}
		else if (this.hierarchyType == HIERARQUIA_4) {		
			application = new Application(name, projectName,
											bechmarkTextField.getText(),
	                      					parametrosTextField.getText(), 
	                          				entradaTextField.getText(),
	                              			saidaTextField.getText(),
	                              			hierarchy);
			application.setTipoSimulacao((String) typeSimulationComboBox
												  .getSelectedItem());
		}
		return application;
	}

	private class AppTreeSelectionlListener implements
		javax.swing.event.TreeSelectionListener {
		
		public void valueChanged(javax.swing.event.TreeSelectionEvent e) {
			DefaultMutableTreeNode node = (DefaultMutableTreeNode)
				tree.getLastSelectedPathComponent();
			
			if (node == null) return;
			if (node.isLeaf()) {
				String appName = (String) node.getUserObject();
				String projName = (String) 
				((DefaultMutableTreeNode) node.getParent()).getUserObject();
				createTab(appName, projName);
			}
		}
	}

	@Action public void createTab(String appName, String projName) {
		Task task = new NewTab(getApplication(), appName, projName);
		task.execute();
		//return task;
	}
	
	private class NewTab extends Task<Void, Void> {
		private String appName;
		private String projName;
		
		public NewTab(org.jdesktop.application.Application app,
				String appName, String projName) {
			super(app);
			this.appName = appName;
			this.projName = projName;
		}
		
		@Override protected Void doInBackground() {
			addTab(appName, projName);
			try {
				loadUpdateMode(caetoManager.search(projName)
						.getApplications().search(appName),
						generalTabbedPane.getTabCount()-1);
			} catch (ElementNotFoundException e1) {
				e1.printStackTrace();
			}
			return null;
		}
	}
	
	private class CloseTabButton extends javax.swing.JPanel
								implements java.awt.event.ActionListener {
		private javax.swing.JTabbedPane pane;
		public CloseTabButton(javax.swing.JTabbedPane pane, int index) {
			this.pane = pane;
			setOpaque(false);
			add(new javax.swing.JLabel(
					pane.getTitleAt(index),
					pane.getIconAt(index),
					javax.swing.JLabel.LEFT));
			Icon closeIcon = getResourceMap().getIcon("closeIcon");
			javax.swing.JButton btClose = new javax.swing.JButton(closeIcon);
			btClose.setPreferredSize(new java.awt.Dimension(
			  closeIcon.getIconWidth()+2, closeIcon.getIconHeight()+2));
			add(btClose);
			btClose.addActionListener(this);
			pane.setTabComponentAt(index, this);
		}
		public void actionPerformed(java.awt.event.ActionEvent e) {
			int i = pane.indexOfTabComponent(this);
			if (i != -1) {
				pane.remove(i);
				componentList.remove(i);
			}
		}
	}
}
